package com.information.service.impl;

import com.information.entity.OperationLog;
import com.information.entity.User;
import com.information.repository.OperationLogRepository;
import com.information.service.OperationLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import java.util.List;
import java.util.HashMap;
import java.util.Map;

@Service
public class OperationLogServiceImpl implements OperationLogService {
    
    private final OperationLogRepository operationLogRepository;
    private final ObjectMapper objectMapper;
    
    @Autowired
    public OperationLogServiceImpl(OperationLogRepository operationLogRepository) {
        this.operationLogRepository = operationLogRepository;
        this.objectMapper = new ObjectMapper();
        
        // 配置ObjectMapper以正确处理Java 8日期时间和防止循环引用
        objectMapper.registerModule(new JavaTimeModule());
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        // 忽略未知属性
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<OperationLog> findAllLogs() {
        return operationLogRepository.findAll();
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<OperationLog> findLogsByUserId(Long userId) {
        return operationLogRepository.findByUserId(userId);
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<OperationLog> findLogsByOperationType(String operationType) {
        return operationLogRepository.findByOperationType(operationType);
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<OperationLog> findLogsByUsername(String username) {
        return operationLogRepository.findByUsername(username);
    }
    
    @Override
    // 使用默认事务传播行为，不需要特殊设置
    public void logOperation(String operationType, User user, String operatedBy) {
        try {
            // 创建数据快照前，确保用户ID已经设置（防止新增用户时ID为null的情况）
            if (user.getId() == null) {
                return;
            }
            
            OperationLog log = new OperationLog();
            log.setOperationType(operationType);
            log.setUserId(user.getId());
            log.setUsername(user.getUsername());
            log.setOperatedBy(operatedBy);
            
            try {
                // 简化JSON序列化，只保留关键属性
                Map<String, Object> userMap = new HashMap<>();
                userMap.put("id", user.getId());
                userMap.put("username", user.getUsername());
                userMap.put("name", user.getName());
                userMap.put("email", user.getEmail());
                userMap.put("phone", user.getPhone());
                userMap.put("age", user.getAge());
                userMap.put("gender", user.getGender());
                userMap.put("address", user.getAddress());
                
                // Convert user object to JSON string for data snapshot
                String userJson = objectMapper.writeValueAsString(userMap);
                log.setDataSnapshot(userJson);
                
                operationLogRepository.save(log);
            } catch (Exception e) {
                System.err.println("JSON序列化失败: " + e.getMessage());
                // 即使序列化失败，我们仍然尝试保存基本的日志信息
                log.setDataSnapshot("{\"error\":\"序列化用户数据失败: " + e.getMessage() + "\"}");
                operationLogRepository.save(log);
            }
        } catch (Exception e) {
            // 记录更详细的错误信息
            System.err.println("记录操作日志失败: " + e.getMessage());
            e.printStackTrace();
            // 不再抛出异常，避免影响主要业务流程
        }
    }
    
    @Override
    @Transactional
    public OperationLog saveLog(OperationLog log) {
        return operationLogRepository.save(log);
    }
} 